package org.acghub.mtdb.core.log;

import org.acghub.mtdb.core.LogKey;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;

public abstract class LogAbstractList<E> extends LogAbstractCollection<E> implements List<E> {
    public LogAbstractList(LogKey logkey, List<E> wrapped) {
        super(logkey, wrapped);
    }

    protected LogAbstractList(LogAbstractCollection<E> root, List<E> wrapped) {
        super(root, wrapped);
    }

    @Override
    public void sort(Comparator<? super E> c) {
        onChange();
        wrapped().sort(c);
    }

    @Override
    public boolean addAll(int index, Collection<? extends E> c) {
        onChange();
        if (wrapped().addAll(index, c)) {
            onAddAll(c);
            return true;
        }
        return false;
    }

    @Override
    public E get(int index) {
        return wrapped().get(index);
    }

    @Override
    public E set(int index, E element) {
        onChange();
        E origin = wrapped().set(index, element);
        onRemove(origin);
        onAdd(element);
        return origin;
    }

    @Override
    public void add(int index, E element) {
        onChange();
        wrapped().add(index, element);
        onAdd(element);
    }

    @Override
    public E remove(int index) {
        onChange();
        E remove = wrapped().remove(index);
        onRemove(remove);
        return remove;
    }

    @Override
    public int indexOf(Object o) {
        return wrapped().indexOf(o);
    }

    @Override
    public int lastIndexOf(Object o) {
        return wrapped().lastIndexOf(o);
    }

    @Override
    public ListIterator<E> listIterator() {
        return new LogListIte(wrapped());
    }

    @Override
    public ListIterator<E> listIterator(int index) {
        return new LogListIte(wrapped(), index);
    }

    @Override
    protected List<E> wrapped() {
        return (List<E>) wrapped;
    }

    protected class LogListIte implements ListIterator<E> {

        private final ListIterator<E> ite;
        private E current;

        LogListIte(List<E> wrapped) {
            ite = wrapped.listIterator();
        }

        LogListIte(List<E> wrapped, int index) {
            ite = wrapped.listIterator(index);
        }

        @Override
        public boolean hasNext() {
            return ite.hasNext();
        }

        @Override
        public E next() {
            return current = ite.next();
        }

        @Override
        public boolean hasPrevious() {
            return ite.hasPrevious();
        }

        @Override
        public E previous() {
            return current = ite.previous();
        }

        @Override
        public int nextIndex() {
            return ite.nextIndex();
        }

        @Override
        public int previousIndex() {
            return ite.previousIndex();
        }

        @Override
        public void remove() {
            onChange();
            ite.remove();
            onRemove(current);
        }

        @Override
        public void set(E e) {
            onChange();
            onRemove(current);
            ite.set(e);
            onAdd(e);

        }

        @Override
        public void add(E e) {
            onChange();
            ite.set(e);
            onAdd(e);
        }
    }
}
